package DyingBaby.backend.exec;

import DyingBaby.backend.common.QueryResult;
import DyingBaby.backend.sql.Lexer;
import DyingBaby.backend.sql.Parser;
import DyingBaby.backend.catalog.Catalog;
import DyingBaby.backend.plan.LogicalExecutor;
import DyingBaby.backend.plan.LogicalPlan;
import DyingBaby.backend.plan.Planner;
import DyingBaby.backend.sql.Ast;

import java.util.List;

/**
 * SQL查询执行器
 * 负责将SQL语句转换为执行计划并执行
 */
public class Executor {
    // 数据库目录（元数据管理器）
    private final Catalog catalog;
    // 查询计划器，用于生成逻辑执行计划
    private final Planner planner;
    // 逻辑执行器，用于执行逻辑计划
    private final LogicalExecutor logicalExecutor;

    /**
     * 构造函数
     * @param catalog 数据库目录（包含表、索引等元数据信息）
     */
    public Executor(Catalog catalog) {
        this.catalog = catalog;
        // 初始化查询计划器
        this.planner = new Planner(catalog);
        // 初始化逻辑执行器
        this.logicalExecutor = new LogicalExecutor(catalog);
    }

    /**
     * 执行SQL语句
     * @param sql 要执行的SQL语句
     * @return 执行结果
     * @throws IllegalArgumentException 当输入的不是支持的语句类型时抛出
     */
    public QueryResult execute(String sql) {
        // 1. 词法分析 - 生成Token流
        System.out.println("=== Token流 ===");
        java.util.List<DyingBaby.backend.sql.Lexer.Token> tokens = new DyingBaby.backend.sql.Lexer(sql).tokenize();
        for (DyingBaby.backend.sql.Lexer.Token token : tokens) {
            System.out.println(token);
        }
        System.out.println();

        // 2. 语法分析 - 生成AST
        System.out.println("=== AST ===");
        //解析：将SQL字符串转换为抽象语法树（AST）
        Object parsed = Parser.parse(sql);
        System.out.println(parsed);
        System.out.println();
        //验证：是否为支持的语句类型（Stmt类型）
        if (!(parsed instanceof Ast.Stmt)) {
            throw new IllegalArgumentException("Unsupported statement");
        }

        // 3. 语义检查 - 检查表是否存在、列是否唯一等
        System.out.println("=== 语义检查结果 ===");
        Ast.Stmt stmt = (Ast.Stmt) parsed;
        if (stmt instanceof Ast.CreateTable) {
            Ast.CreateTable ct = (Ast.CreateTable) stmt;
            System.out.println("检查表名: " + ct.table);
            System.out.println("检查列定义: " + ct.columns);
            System.out.println("检查主键: " + ct.primaryKey);
            System.out.println("语义检查通过 ✓");
        }
        System.out.println();

        // 4. 生成执行计划
        System.out.println("=== 执行计划 ===");
        LogicalPlan plan = planner.plan(stmt);
        System.out.println("计划类型: " + plan.getClass().getSimpleName());
        System.out.println("计划详情: " + plan);
        System.out.println();

        //执行（LogicalExecutor）：执行逻辑计划并返回结果
        String planType = plan.getClass().getSimpleName();
        long startNs = System.nanoTime();
        Object data = logicalExecutor.execute(plan);
        long elapsedMs = (System.nanoTime() - startNs) / 1_000_000L;
        return new QueryResult(data, elapsedMs, planType);
    }
} 